from kindle_app import app
from flask import render_template, request, abort, redirect, url_for, make_response, current_app, session
from werkzeug.security import check_password_hash, generate_password_hash
from .database import db_session, User, Articles
from flask_login import login_user, login_required, logout_user
import json
import random
from time import strftime, localtime
from sqlalchemy import func
from math import ceil
from base64 import b64decode, b64encode
from .generate_code import validate_picture
from io import BytesIO


class KindleUserName:
    def __init__(self, user, password):
        self.user = user
        self._password = password
        self._password_hash = generate_password_hash(password)

    def register(self):
        if len(self._password) < 18 and len(self.user) < 10:
            new_user = User(userName=self.user, password=self._password_hash)
            db_session.add(new_user)
            db_session.commit()
            return True
        else:
            return False

    @classmethod
    def login(cls, name, password):
        if len(name) < 10 and len(password) < 20:
            user = User.query.filter_by(userName=name).first()
            if user is None:
                return False
            if check_password_hash(user.password, password):
                cls.user_instance = user
                cls.username = user.userName
                return True
            else:
                return False
        else:
            return False
        pass

    @classmethod
    def get_user_instance(cls):
        return cls.user_instance

    @classmethod
    def get_username(cls):
        try:
            username = cls.username
        except Exception:
            abort(403)
        else:
            return username


#
# class VerifyCode:
#     code = {}
#
#     @classmethod
#     def set_verify_code(cls, session_id, code_id):
#         if len(cls.code) > 500:
#             cls.code = {}
#         cls.code[session_id] = code_id
#
#     @classmethod
#     def get_verify_code(cls, session_id, verify_code):
#         code = cls.code[session_id]
#         if not code:
#             return False
#         else:
#             cls.code.pop(session_id)
#             if code == verify_code:
#                 return True
#             else:
#                 return False


class ArticleClass:
    @classmethod
    def articles_msg(cls, article_content, id):
        cls.article_content = article_content
        cls.id = id

    @classmethod
    def get_article_content(cls):
        return cls.article_content


@app.route('/', methods=['GET'])
def app_index():
    return redirect(url_for('login'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        code = ''.join([str(random.randint(0, 9)) for i in range(8)])
        cookies = b64encode(code.encode('utf-8', code))
        response = make_response(render_template('login.html'))
        response.set_cookie('id', cookies)
        return response
    elif request.method == 'POST':
        sessions_id = request.cookies.get('id')
        b64_id = b64decode(sessions_id)
        utf_8_id = str(b64_id, 'utf-8')
        if utf_8_id:
            try:
                code = request.form['code']
            except Exception:
                Msg = {'status': 'fail', 'Msg': '登录失败，验证码错误！'}
                return json.dumps(Msg)
            else:
                if session['image'] == code.upper():
                    session.pop('image')
                    try:
                        username = request.form['u']
                        password = request.form['p']
                    except Exception:
                        abort(403)
                    else:
                        if KindleUserName.login(username, password):
                            login_user(KindleUserName.get_user_instance())
                            response = make_response(url_for('index'))
                            response.delete_cookie('code')
                            return response
                        else:
                            Msg = {'status': 'fail', 'Msg': '登录失败，用户名或密码错误！'}
                            response = make_response(json.dumps(Msg))
                            response.delete_cookie('code')
                            return response
                else:
                    Msg = {'status': 'fail', 'Msg': '登录失败，验证码错误！'}
                    return json.dumps(Msg)
        else:
            abort(401)


@app.route('/register', methods=['POST'])
def register():
    try:
        username = request.form['u']
        password = request.form['p']
    except Exception:
        abort(403)
    else:
        new_user = KindleUserName(username, password)
        if new_user.register():
            return 'ok'
        else:
            return 'failed!'


@app.route('/index')
@login_required
def index():
    username = KindleUserName.get_username()
    return render_template('index.html', username=username)


@app.route('/edit', methods=['GET', 'POST'])
@login_required
def edit():
    if request.method == 'GET':
        return render_template('edit.html')
    else:
        try:
            title = request.form['title']
            author = request.form['author']
            content = request.form['content']
        except Exception as e:
            abort(400)
        else:
            a = Articles(title=title, author=author, content=content, time=strftime("%Y-%m-%d %H:%M:%S", localtime()))
            db_session.add(a)
            db_session.commit()
            msg = {'status': 'success', 'msg': '保存成功!'}
            return json.dumps(msg)


# @app.route('/slide_verify', methods=['GET'])
# def slide_verify():
#     web_id = request.cookies.get('id')
#     if not web_id:
#         return url_for('app_index')
#     session_id = str(b64decode(web_id), 'utf-8')
#     code = ''.join([str(random.randint(0, 9)) for i in range(6)])
#     current_app.__setattr__(session_id, code)
#     cookies_code = b64encode(code.encode('utf-8'))
#     # VerifyCode.set_verify_code(session_id, code)
#     #print(current_app.code)
#     msg = {'status': 'ok'}
#     respone = make_response(json.dumps(msg))
#     respone.set_cookie('code', cookies_code)
#     return respone


@app.route('/logout', methods=['GET'])
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))


@app.route('/index_content.html', methods=['GET'])
@login_required
def content():
    username = KindleUserName.get_username()
    return render_template('index_content.html', site_title=username)


@app.route('/articles_list', methods=['GET'])
@login_required
def articles():
    result = db_session.query(func.count(Articles.id)).all()[0]
    max_page_index = {'status': 'success', 'max_index': ceil(int(result[0])/10)}
    return json.dumps(max_page_index)


@app.route('/article/<int:page_id>.html', methods=['GET'])
def article(page_id):
    article_content = db_session.query(Articles).get(page_id)
    ArticleClass.articles_msg(article_content.content, page_id)
    return render_template('articles.html', title=article_content.title, article_author=article_content.author,
                           create_time=article_content.time, content=article_content.content)


@app.route('/get_article_content', methods=['GET'])
def get_article_content():
    try:
        article_content = db_session.query(Articles).get(session['page_id'])
    except Exception:
        msg = {'status': 'fail', 'data': '出现未知错误!'}
    else:
        msg = {'status': 'success', 'data': article_content.content}
    return json.dumps(msg)


# @app.route('/article/update/<int:page_id>', methods=['GET'])
# def update_
@app.route('/article/update/<int:page_id>', methods=['GET'])
@login_required
def update_article_content(page_id):
    session['page_id'] = page_id
    return render_template('article_update.html')


@app.route('/article/content.html', methods=['GET'])
def articles_content():
    return ArticleClass.get_article_content()


@app.route('/article/<int:list_id>')
@login_required
def get_articles_list(list_id):
    page = db_session.query(Articles).limit(10).offset((list_id-1)*10)
    j = 0
    msg = ''
    for i in page:
        j = j + 1
        one_list = '<div class="grid mb2 t-c mt4 ml4 f36 clearfix" onclick="get_article_byId(this)"id="%s" style="height:60px;">\
        <div class="box col-2 h10" >%s</div>\
        <div class="box col-6 h10" >%s</div>\
        <div class="box col-4 h10" style="color: #666666">%s</div>\
        </div>' % (i.id, i.author, i.title, i.time)
        msg = "%s%s" % (msg, one_list)  # msg[j] = {'id': i.id, 'author': i.author, 'title': i.title, 'time': i.time}
    return msg


@app.route('/article_update/<int:list_id>')
@login_required
def update_articles_list(list_id):
    page = db_session.query(Articles).limit(10).offset((list_id-1)*10)
    j = 0
    msg = ''
    for i in page:
        j = j + 1
        one_list = '<div class="grid mb2 t-c mt4 ml4 f36 clearfix" onclick="update_article_byId(this)"id="%s" style="height:60px;">\
        <div class="box col-2 h10" >%s</div>\
        <div class="box col-6 h10" >%s</div>\
        <div class="box col-4 h10" style="color: #666666">%s</div>\
        </div>' % (i.id, i.author, i.title, i.time)
        msg = "%s%s" % (msg, one_list)  # msg[j] = {'id': i.id, 'author': i.author, 'title': i.title, 'time': i.time}
    return msg


@app.route('/article/index', methods=['GET'])
@login_required
def get_index_html():
    return render_template('articles_list.html')


@app.route('/login/code_image')
def verify_code():
    image, code = validate_picture()
    # 图片以二进制形式写入
    buf = BytesIO()
    image.save(buf, 'jpeg')
    buf_str = buf.getvalue()
    # 把buf_str作为response返回前端，并设置首部字段
    response = make_response(buf_str)
    response.headers['Content-Type'] = 'image/gif'
    # 将验证码字符串储存在session中
    session['image'] = code.upper()
    return response


@app.route('/article/update', methods=['GET', 'POST'])
@login_required
def article_update():
    if request.method == 'GET':
        return render_template('article_update_list.html')
    elif request.method == 'POST':
        try:
            update_content = request.form['article_data']
            content1 = db_session.query(Articles).get(session['page_id'])
            content1.content = update_content
            content1.time = strftime("%Y-%m-%d %H:%M:%S", localtime())
            db_session.commit()
        except Exception as e:
            print(e)
            msg = {'status': 'fail', 'data': '发生了一个未知错误!'}
        else:
            msg = {'status': 'success', 'data': '更新成功!'}
        return json.dumps(msg)
    else:
        abort(404)
    pass


@app.route('/delete')
@login_required
def delete_article():
    try:
        content1 = db_session.query(Articles).get(session['page_id'])
        db_session.delete(content1)
        db_session.commit()
        session.pop('page_id')
    except Exception:
        msg = {'status': 'fail', 'data': '发生了未知错误!'}
    else:
        msg = {'status': 'success', 'data': '文章删除成功!'}
    return json.dumps(msg)

    pass


@app.teardown_request
def remove_db_session(exception):
    db_session.remove()

